package c2c

import (
	"errors"
	"fmt"
	"gim-server/apis/ws"
	"gim-server/apis/ws/notify_open_api"
	"gim-server/comsvc"
	"gim-server/consts"
	"gim-server/errs"
	"gim-server/model"
	"gim-server/sdk"
	"gim-server/utils"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"strings"
	"time"
)

type SendC2cMsgArgs struct {
	ToUID       string `json:"to_uid"`
	PreID       string `json:"pre_id"`
	Ext         string `json:"ext"`
	MsgType     string `json:"msg_type"`
	MsgData     string `json:"msg_data"`
	NotPush     bool   `json:"not_push"`
	PushTitle   string `json:"push_title"`
	PushContent string `json:"push_content"`
}

func sendC2cMsg(ctx *gin.Context) {
	var (
		err  error
		args = new(SendC2cMsgArgs)
	)
	if err = ctx.ShouldBindJSON(args); err != nil {
		utils.ERR(ctx, &utils.ErrArgs{
			Code: errs.ApiParamsErr,
			Err:  err,
		})
		return
	}
	msg := new(model.TbC2cMsgRecord)
	msg.PreID = args.PreID
	msg.FromUID = ctx.GetString(consts.UID)
	msg.ToUID = args.ToUID
	msg.Ext = args.Ext
	msg.MsgType = args.MsgType
	msg.MsgData = args.MsgData
	msg.Code = model.SucCode
	msg.Readed = false
	msg.ErrTip = ""
	msg.DelUID = "0"
	msg.CreatedAt = time.Now().Unix()
	db := sdk.DB(ctx)
	canSend := true
	err = db.Transaction(func(tx *gorm.DB) error {
		cvs := new(model.TbConversation)
		if err := db.First(cvs, "from_uid = ? and to_uid = ?", msg.FromUID, msg.ToUID).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				//新建
				cvs.FromUID = msg.FromUID
				cvs.ToUID = msg.ToUID
				cvs.UnreadCount = 0
				cvs.MarkTop = false
				cvs.CreatedAt = time.Now().Unix()
				cvs.UpdatedAt = time.Now().Unix()
				if err := tx.Create(cvs).Error; err != nil {
					return err
				}
			} else {
				return err
			}
		} else {
			//更新
			cvs.UpdatedAt = time.Now().Unix()
			if err := tx.Save(cvs).Error; err != nil {
				return err
			}
		}
		app, _ := comsvc.GetAppInfo(ctx.GetString(consts.AppID))
		if app != nil {
			notifyDto, err := notify_open_api.NotifyBeforeSendC2cMsg(&notify_open_api.NotifyBeforeSendC2cMsgArgs{
				AppID:   ctx.GetString(consts.AppID),
				FromUID: ctx.GetString(consts.UID),
				ToUID:   args.ToUID,
				MsgType: args.MsgType,
				MsgData: args.MsgData,
			})
			if err != nil && !notifyDto.Data.(bool) {
				canSend = false
				msg.Code = model.CbInterceptor
				msg.ErrTip = fmt.Sprintf("%v", notifyDto.Message)
				msg.DelUID = msg.ToUID
				if err := tx.Create(msg).Error; err != nil {
					return err
				}
				return nil
			}
			if !app.IgnoreAudit {
				auditOk := true
				//检查违规
				if msg.MsgType == model.MsgTypeText {
					auditResult, err := sdk.CosAuditText(msg.MsgData)
					if err != nil {
						return err
					}
					if auditResult.Flag != 0 {
						canSend = false
						auditOk = false
					}
				} else if msg.MsgType == model.MsgTypeImage {
					img := new(ws.ImageMsg)
					if err := utils.JsonUnmarshal([]byte(msg.MsgData), img); err != nil {
						return err
					}
					auditResult, err := sdk.CosAuditImage([]string{img.Url})
					if err != nil {
						return err
					}
					if auditResult.Flag != 0 {
						canSend = false
						auditOk = false
					}
				} else if msg.MsgType == model.MsgTypeVideo {
					video := new(ws.VideoMsg)
					if err := utils.JsonUnmarshal([]byte(msg.MsgData), video); err != nil {
						return err
					}
					urls := make([]string, 0)
					split := strings.Split(video.Url, ".")
					for i := 0; i < 3; i++ {
						urls = append(urls, fmt.Sprintf("%s_%d.jpg", split[0], i))
					}
					auditResult, err := sdk.CosAuditImage(urls)
					if err != nil {
						return err
					}
					if auditResult.Flag != 0 {
						canSend = false
						auditOk = false
					}
				}
				if !auditOk {
					canSend = false
					msg.Code = model.AuditCode
					msg.ErrTip = "为了维护一个绿色的网络环境，请勿发布违规内容"
					msg.DelUID = msg.ToUID
					if err := tx.Create(msg).Error; err != nil {
						return err
					}
					return nil
				}
			}
		}

		if err := tx.Create(msg).Error; err != nil {
			return err
		}
		cvs = new(model.TbConversation)
		if err := db.First(cvs, "from_uid = ? and to_uid = ?", msg.ToUID, msg.FromUID).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				//新建
				cvs.FromUID = msg.ToUID
				cvs.ToUID = msg.FromUID
				cvs.UnreadCount = 1
				cvs.MarkTop = false
				cvs.CreatedAt = time.Now().Unix()
				cvs.UpdatedAt = time.Now().Unix()
				if err := tx.Create(cvs).Error; err != nil {
					return err
				}
			} else {
				return err
			}
		} else {
			//更新
			cvs.UnreadCount = cvs.UnreadCount + 1
			cvs.UpdatedAt = time.Now().Unix()
			if err := tx.Save(cvs).Error; err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		utils.ERR(ctx, &utils.ErrArgs{
			Code: errs.ApiSrvErr,
			Err:  err,
		})
		return
	}
	if canSend {
		_ = sdk.AsyncPool().Submit(func() {
			ws.SendC2cMsg(msg, args.NotPush, args.PushTitle, args.PushContent)
		})
	}
	utils.SUC(ctx, msg)
}
